home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-10-28 | 36.5 KB | 1,123 lines |
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- NNNNAAAAMMMMEEEE
- perlXStut - Tutorial for XSUBs
-
- DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
- This tutorial will educate the reader on the steps involved
- in creating a Perl extension. The reader is assumed to have
- access to the _p_e_r_l_g_u_t_s manpage and the _p_e_r_l_x_s manpage.
-
- This tutorial starts with very simple examples and becomes
- more complex, with each new example adding new features.
- Certain concepts may not be completely explained until later
- in the tutorial to ease the reader slowly into building
- extensions.
-
- VVVVEEEERRRRSSSSIIIIOOOONNNN CCCCAAAAVVVVEEEEAAAATTTT
-
- This tutorial tries hard to keep up with the latest
- development versions of Perl. This often means that it is
- sometimes in advance of the latest released version of Perl,
- and that certain features described here might not work on
- earlier versions. This section will keep track of when
- various features were added to Perl 5.
-
- +o In versions of Perl 5.002 prior to the gamma version,
- the test script in Example 1 will not function properly.
- You need to change the "use lib" line to read:
-
- use lib './blib';
-
-
- +o In versions of Perl 5.002 prior to version beta 3, the
- line in the .xs file about "PROTOTYPES: DISABLE" will
- cause a compiler error. Simply remove that line from
- the file.
-
- +o In versions of Perl 5.002 prior to version 5.002b1h, the
- test.pl file was not automatically created by h2xs.
- This means that you cannot say "make test" to run the
- test script. You will need to add the following line
- before the "use extension" statement:
-
- use lib './blib';
-
-
- +o In versions 5.000 and 5.001, instead of using the above
- line, you will need to use the following line:
-
- BEGIN { unshift(@INC, "./blib") }
-
-
- +o This document assumes that the executable named "perl"
- is Perl version 5. Some systems may have installed Perl
-
-
-
- Page 1 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- version 5 as "perl5".
-
- DDDDYYYYNNNNAAAAMMMMIIIICCCC VVVVEEEERRRRSSSSUUUUSSSS SSSSTTTTAAAATTTTIIIICCCC
-
- It is commonly thought that if a system does not have the
- capability to load a library dynamically, you cannot build
- XSUBs. This is incorrect. You _c_a_n build them, but you must
- link the XSUB's subroutines with the rest of Perl, creating
- a new executable. This situation is similar to Perl 4.
-
- This tutorial can still be used on such a system. The XSUB
- build mechanism will check the system and build a
- dynamically-loadable library if possible, or else a static
- library and then, optionally, a new statically-linked
- executable with that static library linked in.
-
- Should you wish to build a statically-linked executable on a
- system which can dynamically load libraries, you may, in all
- the following examples, where the command "make" with no
- arguments is executed, run the command "make perl" instead.
-
- If you have generated such a statically-linked executable by
- choice, then instead of saying "make test", you should say
- "make test_static". On systems that cannot build
- dynamically-loadable libraries at all, simply saying "make
- test" is sufficient.
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEE 1111
-
- Our first extension will be very simple. When we call the
- routine in the extension, it will print out a well-known
- message and return.
-
- Run h2xs -A -n Mytest. This creates a directory named
- Mytest, possibly under ext/ if that directory exists in the
- current working directory. Several files will be created in
- the Mytest dir, including MANIFEST, Makefile.PL, Mytest.pm,
- Mytest.xs, test.pl, and Changes.
-
- The MANIFEST file contains the names of all the files
- created.
-
- The file Makefile.PL should look something like this:
-
-
-
-
-
-
-
-
-
-
-
-
- Page 2 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- use ExtUtils::MakeMaker;
- # See lib/ExtUtils/MakeMaker.pm for details of how to influence
- # the contents of the Makefile that is written.
- WriteMakefile(
- 'NAME' => 'Mytest',
- 'VERSION_FROM' => 'Mytest.pm', # finds $VERSION
- 'LIBS' => [''], # e.g., '-lm'
- 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
- 'INC' => '', # e.g., '-I/usr/include/other'
- );
-
- The file Mytest.pm should start with something like this:
-
- package Mytest;
-
- require Exporter;
- require DynaLoader;
-
- @ISA = qw(Exporter DynaLoader);
- # Items to export into callers namespace by default. Note: do not export
- # names by default without a very good reason. Use EXPORT_OK instead.
- # Do not simply export all your public functions/methods/constants.
- @EXPORT = qw(
-
- );
- $VERSION = '0.01';
-
- bootstrap Mytest $VERSION;
-
- # Preloaded methods go here.
-
- # Autoload methods go after __END__, and are processed by the autosplit program.
-
- 1;
- __END__
- # Below is the stub of documentation for your module. You better edit it!
-
- And the Mytest.xs file should look something like this:
-
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "EXTERN.h"
- #include "perl.h"
- #include "XSUB.h"
- #ifdef __cplusplus
- }
- #endif
-
- PROTOTYPES: DISABLE
-
- MODULE = Mytest PACKAGE = Mytest
-
-
-
- Page 3 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- Let's edit the .xs file by adding this to the end of the
- file:
-
- void
- hello()
- CODE:
- printf("Hello, world!\n");
-
- Now we'll run "perl Makefile.PL". This will create a real
- Makefile, which make needs. Its output looks something
- like:
-
- % perl Makefile.PL
- Checking if your kit is complete...
- Looks good
- Writing Makefile for Mytest
- %
-
- Now, running make will produce output that looks something
- like this (some long lines shortened for clarity):
-
- % make
- umask 0 && cp Mytest.pm ./blib/Mytest.pm
- perl xsubpp -typemap typemap Mytest.xs >Mytest.tc && mv Mytest.tc Mytest.c
- cc -c Mytest.c
- Running Mkbootstrap for Mytest ()
- chmod 644 Mytest.bs
- LD_RUN_PATH="" ld -o ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl -b Mytest.o
- chmod 755 ./blib/PA-RISC1.1/auto/Mytest/Mytest.sl
- cp Mytest.bs ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs
- chmod 644 ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs
-
- Now, although there is already a test.pl template ready for
- us, for this example only, we'll create a special test
- script. Create a file called hello that looks like this:
-
- #! /opt/perl5/bin/perl
-
- use ExtUtils::testlib;
-
- use Mytest;
-
- Mytest::hello();
-
- Now we run the script and we should see the following
- output:
-
- % perl hello
- Hello, world!
- %
-
-
-
-
-
- Page 4 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEE 2222
-
- Now let's add to our extension a subroutine that will take a
- single argument and return 1 if the argument is even, 0 if
- the argument is odd.
-
- Add the following to the end of Mytest.xs:
-
- int
- is_even(input)
- int input
- CODE:
- RETVAL = (input % 2 == 0);
- OUTPUT:
- RETVAL
-
- There does not need to be white space at the start of the
- "int input" line, but it is useful for improving
- readability. The semi-colon at the end of that line is also
- optional.
-
- Any white space may be between the "int" and "input". It is
- also okay for the four lines starting at the "CODE:" line to
- not be indented. However, for readability purposes, it is
- suggested that you indent them 8 spaces (or one normal tab
- stop).
-
- Now rerun make to rebuild our new shared library.
-
- Now perform the same steps as before, generating a Makefile
- from the Makefile.PL file, and running make.
-
- To test that our extension works, we now need to look at the
- file test.pl. This file is set up to imitate the same kind
- of testing structure that Perl itself has. Within the test
- script, you perform a number of tests to confirm the
- behavior of the extension, printing "ok" when the test is
- correct, "not ok" when it is not. Change the print
- statement in the BEGIN block to print "1..4", and add the
- following code to the end of the file:
-
- print &Mytest::is_even(0) == 1 ? "ok 2" : "not ok 2", "\n";
- print &Mytest::is_even(1) == 0 ? "ok 3" : "not ok 3", "\n";
- print &Mytest::is_even(2) == 1 ? "ok 4" : "not ok 4", "\n";
-
- We will be calling the test script through the command "make
- test". You should see output that looks something like
- this:
-
-
-
-
-
-
-
- Page 5 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- % make test
- PERL_DL_NONLAZY=1 /opt/perl5.002b2/bin/perl (lots of -I arguments) test.pl
- 1..4
- ok 1
- ok 2
- ok 3
- ok 4
- %
-
-
- WWWWHHHHAAAATTTT HHHHAAAASSSS GGGGOOOONNNNEEEE OOOONNNN????
-
- The program h2xs is the starting point for creating
- extensions. In later examples we'll see how we can use h2xs
- to read header files and generate templates to connect to C
- routines.
-
- h2xs creates a number of files in the extension directory.
- The file Makefile.PL is a perl script which will generate a
- true Makefile to build the extension. We'll take a closer
- look at it later.
-
- The files <extension>.pm and <extension>.xs contain the meat
- of the extension. The .xs file holds the C routines that
- make up the extension. The .pm file contains routines that
- tell Perl how to load your extension.
-
- Generating and invoking the Makefile created a directory
- blib (which stands for "build library") in the current
- working directory. This directory will contain the shared
- library that we will build. Once we have tested it, we can
- install it into its final location.
-
- Invoking the test script via "make test" did something very
- important. It invoked perl with all those -I arguments so
- that it could find the various files that are part of the
- extension.
-
- It is _v_e_r_y important that while you are still testing
- extensions that you use "make test". If you try to run the
- test script all by itself, you will get a fatal error.
-
- Another reason it is important to use "make test" to run
- your test script is that if you are testing an upgrade to an
- already-existing version, using "make test" insures that you
- use your new extension, not the already-existing version.
-
- When Perl sees a use extension;, it searches for a file with
- the same name as the use'd extension that has a .pm suffix.
- If that file cannot be found, Perl dies with a fatal error.
- The default search path is contained in the @INC array.
-
-
-
-
- Page 6 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- In our case, Mytest.pm tells perl that it will need the
- Exporter and Dynamic Loader extensions. It then sets the
- @ISA and @EXPORT arrays and the $VERSION scalar; finally it
- tells perl to bootstrap the module. Perl will call its
- dynamic loader routine (if there is one) and load the shared
- library.
-
- The two arrays that are set in the .pm file are very
- important. The @ISA array contains a list of other packages
- in which to search for methods (or subroutines) that do not
- exist in the current package. The @EXPORT array tells Perl
- which of the extension's routines should be placed into the
- calling package's namespace.
-
- It's important to select what to export carefully. Do NOT
- export method names and do NOT export anything else _b_y
- _d_e_f_a_u_l_t without a good reason.
-
- As a general rule, if the module is trying to be object-
- oriented then don't export anything. If it's just a
- collection of functions then you can export any of the
- functions via another array, called @EXPORT_OK.
-
- See the _p_e_r_l_m_o_d manpage for more information.
-
- The $VERSION variable is used to ensure that the .pm file
- and the shared library are "in sync" with each other. Any
- time you make changes to the .pm or .xs files, you should
- increment the value of this variable.
-
- WWWWRRRRIIIITTTTIIIINNNNGGGG GGGGOOOOOOOODDDD TTTTEEEESSSSTTTT SSSSCCCCRRRRIIIIPPPPTTTTSSSS
-
- The importance of writing good test scripts cannot be
- overemphasized. You should closely follow the "ok/not ok"
- style that Perl itself uses, so that it is very easy and
- unambiguous to determine the outcome of each test case.
- When you find and fix a bug, make sure you add a test case
- for it.
-
- By running "make test", you ensure that your test.pl script
- runs and uses the correct version of your extension. If you
- have many test cases, you might want to copy Perl's test
- style. Create a directory named "t", and ensure all your
- test files end with the suffix ".t". The Makefile will
- properly run all these test files.
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEE 3333
-
- Our third extension will take one argument as its input,
- round off that value, and set the _a_r_g_u_m_e_n_t to the rounded
- value.
-
-
-
-
- Page 7 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- Add the following to the end of Mytest.xs:
-
- void
- round(arg)
- double arg
- CODE:
- if (arg > 0.0) {
- arg = floor(arg + 0.5);
- } else if (arg < 0.0) {
- arg = ceil(arg - 0.5);
- } else {
- arg = 0.0;
- }
- OUTPUT:
- arg
-
- Edit the Makefile.PL file so that the corresponding line
- looks like this:
-
- 'LIBS' => ['-lm'], # e.g., '-lm'
-
- Generate the Makefile and run make. Change the BEGIN block
- to print out "1..9" and add the following to test.pl:
-
- $i = -1.5; &Mytest::round($i); print $i == -2.0 ? "ok 5" : "not ok 5", "\n";
- $i = -1.1; &Mytest::round($i); print $i == -1.0 ? "ok 6" : "not ok 6", "\n";
- $i = 0.0; &Mytest::round($i); print $i == 0.0 ? "ok 7" : "not ok 7", "\n";
- $i = 0.5; &Mytest::round($i); print $i == 1.0 ? "ok 8" : "not ok 8", "\n";
- $i = 1.2; &Mytest::round($i); print $i == 1.0 ? "ok 9" : "not ok 9", "\n";
-
- Running "make test" should now print out that all nine tests
- are okay.
-
- You might be wondering if you can round a constant. To see
- what happens, add the following line to test.pl temporarily:
-
- &Mytest::round(3);
-
- Run "make test" and notice that Perl dies with a fatal
- error. Perl won't let you change the value of constants!
-
- WWWWHHHHAAAATTTT''''SSSS NNNNEEEEWWWW HHHHEEEERRRREEEE????
-
- Two things are new here. First, we've made some changes to
- Makefile.PL. In this case, we've specified an extra library
- to link in, the math library libm. We'll talk later about
- how to write XSUBs that can call every routine in a library.
-
- Second, the value of the function is being passed back not
- as the function's return value, but through the same
- variable that was passed into the function.
-
-
-
-
- Page 8 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- IIIINNNNPPPPUUUUTTTT AAAANNNNDDDD OOOOUUUUTTTTPPPPUUUUTTTT PPPPAAAARRRRAAAAMMMMEEEETTTTEEEERRRRSSSS
-
- You specify the parameters that will be passed into the XSUB
- just after you declare the function return value and name.
- Each parameter line starts with optional white space, and
- may have an optional terminating semicolon.
-
- The list of output parameters occurs after the OUTPUT:
- directive. The use of RETVAL tells Perl that you wish to
- send this value back as the return value of the XSUB
- function. In Example 3, the value we wanted returned was
- contained in the same variable we passed in, so we listed it
- (and not RETVAL) in the OUTPUT: section.
-
- TTTTHHHHEEEE XXXXSSSSUUUUBBBBPPPPPPPP CCCCOOOOMMMMPPPPIIIILLLLEEEERRRR
-
- The compiler xsubpp takes the XS code in the .xs file and
- converts it into C code, placing it in a file whose suffix
- is .c. The C code created makes heavy use of the C
- functions within Perl.
-
- TTTTHHHHEEEE TTTTYYYYPPPPEEEEMMMMAAAAPPPP FFFFIIIILLLLEEEE
-
- The xsubpp compiler uses rules to convert from Perl's data
- types (scalar, array, etc.) to C's data types (int, char *,
- etc.). These rules are stored in the typemap file
- ($PERLLIB/ExtUtils/typemap). This file is split into three
- parts.
-
- The first part attempts to map various C data types to a
- coded flag, which has some correspondence with the various
- Perl types. The second part contains C code which xsubpp
- uses for input parameters. The third part contains C code
- which xsubpp uses for output parameters. We'll talk more
- about the C code later.
-
- Let's now take a look at a portion of the .c file created
- for our extension.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 9 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- XS(XS_Mytest_round)
- {
- dXSARGS;
- if (items != 1)
- croak("Usage: Mytest::round(arg)");
- {
- double arg = (double)SvNV(ST(0)); /* XXXXX */
- if (arg > 0.0) {
- arg = floor(arg + 0.5);
- } else if (arg < 0.0) {
- arg = ceil(arg - 0.5);
- } else {
- arg = 0.0;
- }
- sv_setnv(ST(0), (double)arg); /* XXXXX */
- }
- XSRETURN(1);
- }
-
- Notice the two lines marked with "XXXXX". If you check the
- first section of the typemap file, you'll see that doubles
- are of type T_DOUBLE. In the INPUT section, an argument
- that is T_DOUBLE is assigned to the variable arg by calling
- the routine SvNV on something, then casting it to double,
- then assigned to the variable arg. Similarly, in the OUTPUT
- section, once arg has its final value, it is passed to the
- sv_setnv function to be passed back to the calling
- subroutine. These two functions are explained in the
- _p_e_r_l_g_u_t_s manpage; we'll talk more later about what that
- "_S_T(0)" means in the section on the argument stack.
-
- WWWWAAAARRRRNNNNIIIINNNNGGGG
-
- In general, it's not a good idea to write extensions that
- modify their input parameters, as in Example 3. However, to
- accommodate better calling pre-existing C routines, which
- often do modify their input parameters, this behavior is
- tolerated. The next example will show how to do this.
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEE 4444
-
- In this example, we'll now begin to write XSUBs that will
- interact with predefined C libraries. To begin with, we
- will build a small library of our own, then let h2xs write
- our .pm and .xs files for us.
-
- Create a new directory called Mytest2 at the same level as
- the directory Mytest. In the Mytest2 directory, create
- another directory called mylib, and cd into that directory.
-
- Here we'll create some files that will generate a test
- library. These will include a C source file and a header
-
-
-
- Page 10 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- file. We'll also create a Makefile.PL in this directory.
- Then we'll make sure that running make at the Mytest2 level
- will automatically run this Makefile.PL file and the
- resulting Makefile.
-
- In the testlib directory, create a file mylib.h that looks
- like this:
-
- #define TESTVAL 4
-
- extern double foo(int, long, const char*);
-
- Also create a file mylib.c that looks like this:
-
- #include <stdlib.h>
- #include "./mylib.h"
-
- double
- foo(a, b, c)
- int a;
- long b;
- const char * c;
- {
- return (a + b + atof(c) + TESTVAL);
- }
-
- And finally create a file Makefile.PL that looks like this:
-
- use ExtUtils::MakeMaker;
- $Verbose = 1;
- WriteMakefile(
- NAME => 'Mytest2::mylib',
- SKIP => [qw(all static static_lib dynamic dynamic_lib)],
- clean => {'FILES' => 'libmylib$(LIB_EXT)'},
- );
-
- sub MY::top_targets {
- '
- all :: static
-
- static :: libmylib$(LIB_EXT)
-
- libmylib$(LIB_EXT): $(O_FILES)
- $(AR) cr libmylib$(LIB_EXT) $(O_FILES)
- $(RANLIB) libmylib$(LIB_EXT)
-
- ';
- }
-
- We will now create the main top-level Mytest2 files. Change
- to the directory above Mytest2 and run the following
- command:
-
-
-
- Page 11 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- % h2xs -O -n Mytest2 ./Mytest2/mylib/mylib.h
-
- This will print out a warning about overwriting Mytest2, but
- that's okay. Our files are stored in Mytest2/mylib, and
- will be untouched.
-
- The normal Makefile.PL that h2xs generates doesn't know
- about the mylib directory. We need to tell it that there is
- a subdirectory and that we will be generating a library in
- it. Let's add the following key-value pair to the
- WriteMakefile call:
-
- 'MYEXTLIB' => 'mylib/libmylib$(LIB_EXT)',
-
- and a new replacement subroutine too:
-
- sub MY::postamble {
- '
- $(MYEXTLIB): mylib/Makefile
- cd mylib && $(MAKE) $(PASTHRU)
- ';
- }
-
- (Note: Most makes will require that there be a tab character
- that indents the line cd mylib && $(MAKE) $(PASTHRU),
- similarly for the Makefile in the subdirectory.)
-
- Let's also fix the MANIFEST file so that it accurately
- reflects the contents of our extension. The single line
- that says "mylib" should be replaced by the following three
- lines:
-
- mylib/Makefile.PL
- mylib/mylib.c
- mylib/mylib.h
-
- To keep our namespace nice and unpolluted, edit the .pm file
- and change the lines setting @EXPORT to @EXPORT_OK (there
- are two: one in the line beginning "use vars" and one
- setting the array itself). Finally, in the .xs file, edit
- the #include line to read:
-
- #include "mylib/mylib.h"
-
- And also add the following function definition to the end of
- the .xs file:
-
-
-
-
-
-
-
-
-
- Page 12 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- double
- foo(a,b,c)
- int a
- long b
- const char * c
- OUTPUT:
- RETVAL
-
- Now we also need to create a typemap file because the
- default Perl doesn't currently support the const char *
- type. Create a file called typemap and place the following
- in it:
-
- const char * T_PV
-
- Now run perl on the top-level Makefile.PL. Notice that it
- also created a Makefile in the mylib directory. Run make
- and see that it does cd into the mylib directory and run
- make in there as well.
-
- Now edit the test.pl script and change the BEGIN block to
- print "1..4", and add the following lines to the end of the
- script:
-
- print &Mytest2::foo(1, 2, "Hello, world!") == 7 ? "ok 2\n" : "not ok 2\n";
- print &Mytest2::foo(1, 2, "0.0") == 7 ? "ok 3\n" : "not ok 3\n";
- print abs(&Mytest2::foo(0, 0, "-3.4") - 0.6) <= 0.01 ? "ok 4\n" : "not ok 4\n";
-
- (When dealing with floating-point comparisons, it is often
- useful not to check for equality, but rather the difference
- being below a certain epsilon factor, 0.01 in this case)
-
- Run "make test" and all should be well.
-
- WWWWHHHHAAAATTTT HHHHAAAASSSS HHHHAAAAPPPPPPPPEEEENNNNEEEEDDDD HHHHEEEERRRREEEE????
-
- Unlike previous examples, we've now run h2xs on a real
- include file. This has caused some extra goodies to appear
- in both the .pm and .xs files.
-
- +o In the .xs file, there's now a #include declaration with
- the full path to the mylib.h header file.
-
- +o There's now some new C code that's been added to the .xs
- file. The purpose of the constant routine is to make
- the values that are #define'd in the header file
- available to the Perl script (in this case, by calling
- &main::TESTVAL). There's also some XS code to allow
- calls to the constant routine.
-
- +o The .pm file has exported the name TESTVAL in the
- @EXPORT array. This could lead to name clashes. A good
-
-
-
- Page 13 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- rule of thumb is that if the #define is going to be used
- by only the C routines themselves, and not by the user,
- they should be removed from the @EXPORT array.
- Alternately, if you don't mind using the "fully
- qualified name" of a variable, you could remove most or
- all of the items in the @EXPORT array.
-
- +o If our include file contained #include directives, these
- would not be processed at all by h2xs. There is no good
- solution to this right now.
-
- We've also told Perl about the library that we built in the
- mylib subdirectory. That required the addition of only the
- MYEXTLIB variable to the WriteMakefile call and the
- replacement of the postamble subroutine to cd into the
- subdirectory and run make. The Makefile.PL for the library
- is a bit more complicated, but not excessively so. Again we
- replaced the postamble subroutine to insert our own code.
- This code specified simply that the library to be created
- here was a static archive (as opposed to a dynamically
- loadable library) and provided the commands to build it.
-
- SSSSPPPPEEEECCCCIIIIFFFFYYYYIIIINNNNGGGG AAAARRRRGGGGUUUUMMMMEEEENNNNTTTTSSSS TTTTOOOO XXXXSSSSUUUUBBBBPPPPPPPP
-
- With the completion of Example 4, we now have an easy way to
- simulate some real-life libraries whose interfaces may not
- be the cleanest in the world. We shall now continue with a
- discussion of the arguments passed to the xsubpp compiler.
-
- When you specify arguments in the .xs file, you are really
- passing three pieces of information for each one listed.
- The first piece is the order of that argument relative to
- the others (first, second, etc). The second is the type of
- argument, and consists of the type declaration of the
- argument (e.g., int, char*, etc). The third piece is the
- exact way in which the argument should be used in the call
- to the library function from this XSUB. This would mean
- whether or not to place a "&" before the argument or not,
- meaning the argument expects to be passed the address of the
- specified data type.
-
- There is a difference between the two arguments in this
- hypothetical function:
-
- int
- foo(a,b)
- char &a
- char * b
-
- The first argument to this function would be treated as a
- char and assigned to the variable a, and its address would
- be passed into the function foo. The second argument would
-
-
-
- Page 14 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- be treated as a string pointer and assigned to the variable
- b. The _v_a_l_u_e of b would be passed into the function foo.
- The actual call to the function foo that xsubpp generates
- would look like this:
-
- foo(&a, b);
-
- Xsubpp will identically parse the following function
- argument lists:
-
- char &a
- char&a
- char & a
-
- However, to help ease understanding, it is suggested that
- you place a "&" next to the variable name and away from the
- variable type), and place a "*" near the variable type, but
- away from the variable name (as in the complete example
- above). By doing so, it is easy to understand exactly what
- will be passed to the C function -- it will be whatever is
- in the "last column".
-
- You should take great pains to try to pass the function the
- type of variable it wants, when possible. It will save you
- a lot of trouble in the long run.
-
- TTTTHHHHEEEE AAAARRRRGGGGUUUUMMMMEEEENNNNTTTT SSSSTTTTAAAACCCCKKKK
-
- If we look at any of the C code generated by any of the
- examples except example 1, you will notice a number of
- references to _S_T(n), where n is usually 0. The "ST" is
- actually a macro that points to the n'th argument on the
- argument stack. _S_T(0) is thus the first argument passed to
- the XSUB, _S_T(1) is the second argument, and so on.
-
- When you list the arguments to the XSUB in the .xs file,
- that tells xsubpp which argument corresponds to which of the
- argument stack (i.e., the first one listed is the first
- argument, and so on). You invite disaster if you do not
- list them in the same order as the function expects them.
-
- EEEEXXXXTTTTEEEENNNNDDDDIIIINNNNGGGG YYYYOOOOUUUURRRR EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNN
-
- Sometimes you might want to provide some extra methods or
- subroutines to assist in making the interface between Perl
- and your extension simpler or easier to understand. These
- routines should live in the .pm file. Whether they are
- automatically loaded when the extension itself is loaded or
- loaded only when called depends on where in the .pm file the
- subroutine definition is placed.
-
-
-
-
-
- Page 15 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
- DDDDOOOOCCCCUUUUMMMMEEEENNNNTTTTIIIINNNNGGGG YYYYOOOOUUUURRRR EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNN
-
- There is absolutely no excuse for not documenting your
- extension. Documentation belongs in the .pm file. This
- file will be fed to pod2man, and the embedded documentation
- will be converted to the manpage format, then placed in the
- blib directory. It will be copied to Perl's man page
- directory when the extension is installed.
-
- You may intersperse documentation and Perl code within the
- .pm file. In fact, if you want to use method autoloading,
- you must do this, as the comment inside the .pm file
- explains.
-
- See the _p_e_r_l_p_o_d manpage for more information about the pod
- format.
-
- IIIINNNNSSSSTTTTAAAALLLLLLLLIIIINNNNGGGG YYYYOOOOUUUURRRR EEEEXXXXTTTTEEEENNNNSSSSIIIIOOOONNNN
-
- Once your extension is complete and passes all its tests,
- installing it is quite simple: you simply run "make
- install". You will either need to have write permission
- into the directories where Perl is installed, or ask your
- system administrator to run the make for you.
-
- SSSSEEEEEEEE AAAALLLLSSSSOOOO
-
- For more information, consult the _p_e_r_l_g_u_t_s manpage, the
- _p_e_r_l_x_s manpage, the _p_e_r_l_m_o_d manpage, and the _p_e_r_l_p_o_d
- manpage.
-
- AAAAuuuutttthhhhoooorrrr
-
- Jeff Okamoto <_o_k_a_m_o_t_o@_c_o_r_p._h_p._c_o_m>
-
- Reviewed and assisted by Dean Roehrich, Ilya Zakharevich,
- Andreas Koenig, and Tim Bunce.
-
- LLLLaaaasssstttt CCCChhhhaaaannnnggggeeeedddd
-
- 1996/7/10
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 16 (printed 10/23/98)
-
-
-
-
-
-
- PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111)))) 22223333////JJJJuuuullll////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) PPPPEEEERRRRLLLLXXXXSSSSTTTTUUUUTTTT((((1111))))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 17 (printed 10/23/98)
-
-
-
-
-
-
-